/*******************************************************************************
 * Copyright (c) 2007 University of Oslo.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     University of Oslo - initial API and implementation
 *******************************************************************************/

package com.cea.papyrus.diagram.sequence.sedi.figures;

import java.util.List;

import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Layer;
import org.eclipse.draw2d.geometry.Rectangle;

/**
 * This class helps coordinating the vertical position of anchors.
 * It is only a temporary solution, awaiting a redesign of the
 * anchor and layout subsystem.
 * 
 * TODO new anchor/layout strategy 
 * 
 * @author frankd@ifi.uio.no
 */
public class Grid {

	// The vertical distance between the anchors
	public static final int ANCHOR_DELTA = 5;
	
	// The vertical distance to reserve for labels on connections
	// originating at the first anchor
	public static final int RESERVE = 11;
	
	@SuppressWarnings("unchecked")
	public static int findNextGridLine(final IFigure figure, final int offset) {
		// We basically want the Frame figure to decide the grid,
		// that is to say: "anchor origo" is the top left corner of the 
		// frame figure. Every figure lays out its anchors relative to
		// this origo. In particular, the vertical coordinate of each
		// anchor is an integral multiplum of the ANCHOR_DELTA constant.
		
		// TODO This is a complete mess!!! Clean up
		
		final Rectangle ownerBounds = figure.getBounds().getCopy();
		IFigure f = figure;
		if (f instanceof InteractionFigure)
			ownerBounds.y = -figure.getInsets().top;
		else {
			do {
				IFigure parent = f.getParent();
				if (parent != null && !(parent instanceof InteractionFigure))
					f.translateToParent(ownerBounds);
				f = parent;
			}
			while (!(f instanceof Layer || f instanceof InteractionFigure));

			if (f instanceof Layer) {
				// We couldn't find a parent Frame; let's then try to search 
				// downwards from the layer and find a frame that overlaps
				// the figure - if so, we align with this frame.
				IFigure best = null;
				for (final IFigure child : (List<IFigure>) f.getChildren()) {
					if (child instanceof InteractionFigure) {
						final Rectangle intersection = 
							figure.getBounds().getIntersection(child.getBounds());
						if (!intersection.isEmpty()) {
							best = child;
							break;
						}
					}
				}
				
				if (best != null) {
					ownerBounds.x /= 2; ownerBounds.y /= 2;
					best.translateFromParent(ownerBounds);
					ownerBounds.y -= 2;
				}
			}
		}
		
		final int ruler = ownerBounds.y + /*figure.getInsets().top*/ + offset;
		int rest = ruler % ANCHOR_DELTA;
		if (rest != 0)
			return offset + ANCHOR_DELTA - ruler % ANCHOR_DELTA;
		else
			return offset;
	}

	public static int restoreGridLine(final IFigure figure, final int offset) {
		int excess = offset % ANCHOR_DELTA;
		return findNextGridLine(figure, offset - excess);
		//return findNextGridLine(figure, offset - ANCHOR_DELTA + 1);
		//offset / ANCHOR_DELTA
	}
	
	public static int findPreviousGridLine(final IFigure figure, final int offset) {
		int gridline = findNextGridLine(figure, offset); 
		return (gridline > offset) ? gridline - ANCHOR_DELTA : offset;
	}
}
